package com.ruoyi.generator.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.generator.domain.GenTableColumn;
import com.ruoyi.generator.mapper.GenTableColumnMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;
import java.sql.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 业务字段 服务层实现
 *
 * @author ruoyi
 */
@Service
public class GenTableColumnServiceImpl extends ServiceImpl<GenTableColumnMapper, GenTableColumn> implements IGenTableColumnService {
    @Autowired
    private GenTableColumnMapper genTableColumnMapper;

    @Autowired
    private DataSource dataSource;
    /**
     * 查询业务字段列表
     *
     * @param tableId 业务字段编号
     * @return 业务字段集合
     */
    @Override
    public List<GenTableColumn> selectGenTableColumnListByTableId(Long tableId) {
        LambdaQueryWrapper<GenTableColumn> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(GenTableColumn::getTableId, tableId)
                .orderByAsc(GenTableColumn::getSort);
        return baseMapper.selectList(wrapper);
    }

    /**
     * 新增业务字段
     *
     * @param genTableColumn 业务字段信息
     * @return 结果
     */
    @Override
    public int insertGenTableColumn(GenTableColumn genTableColumn) {
        return baseMapper.insert(genTableColumn);
    }

    /**
     * 修改业务字段
     *
     * @param genTableColumn 业务字段信息
     * @return 结果
     */
    @Override
    public int updateGenTableColumn(GenTableColumn genTableColumn) {
        return baseMapper.updateById(genTableColumn);
    }

    /**
     * 删除业务字段对象
     *
     * @param id 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteGenTableColumnById(Long id) {
        return baseMapper.deleteById(id);
    }

    /**
     * 删除业务字段对象
     *
     * @param ids 需要删除的数据ID集合
     * @return 结果
     */
    @Override
    public int deleteGenTableColumnByIds(Long[] ids) {
        return baseMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 根据表名称查询列信息
     *
     * @param tableName 表名称
     * @return 列信息
     */
    @Override
    public List<GenTableColumn> selectDbTableColumnsByName(String tableName) {
        List<GenTableColumn> columnList = new ArrayList<>();

        try (Connection connection = dataSource.getConnection()) {
            DatabaseMetaData metaData = connection.getMetaData();

            // 获取当前数据库信息
            String catalog = connection.getCatalog();
            String schema = connection.getSchema();

            // 获取列信息
            List<ColumnMeta> columnMetas = getColumnMetaInfo(metaData, catalog, schema, tableName);

            // 获取主键信息
            Set<String> primaryKeys = getPrimaryKeyColumns(metaData, catalog, schema, tableName);

            // 转换为 GenTableColumn 对象
            columnList = convertToGenTableColumns(columnMetas, primaryKeys);

        } catch (SQLException e) {
            throw new RuntimeException("获取表字段信息失败: " + e.getMessage(), e);
        }

        return columnList;
    }
    /**
     * 删除业务字段
     *
     * @param genTableColumns 列数据
     * @return 结果
     */
    @Override
    public int deleteGenTableColumns(List<GenTableColumn> genTableColumns)
    {
        List<Long> columnIds = genTableColumns.stream()
                .map(GenTableColumn::getColumnId)
                .collect(Collectors.toList());

        if (columnIds.isEmpty()) {
            return 0;
        }

        return baseMapper.deleteBatchIds(columnIds);
    }
    /**
     * 获取列元数据信息
     */
    private List<ColumnMeta> getColumnMetaInfo(DatabaseMetaData metaData,
                                               String catalog, String schema,
                                               String tableName) throws SQLException {
        List<ColumnMeta> columnMetas = new ArrayList<>();

        try (ResultSet columns = metaData.getColumns(catalog, schema, tableName, "%")) {
            while (columns.next()) {
                ColumnMeta meta = new ColumnMeta();
                meta.columnName = columns.getString("COLUMN_NAME");
                meta.dataType = columns.getInt("DATA_TYPE");
                meta.typeName = columns.getString("TYPE_NAME");
                meta.columnSize = columns.getInt("COLUMN_SIZE");
                meta.decimalDigits = columns.getInt("DECIMAL_DIGITS");
                meta.isNullable = columns.getString("IS_NULLABLE");
                meta.remarks = columns.getString("REMARKS");
                meta.ordinalPosition = columns.getInt("ORDINAL_POSITION");
                meta.isAutoIncrement = "YES".equals(columns.getString("IS_AUTOINCREMENT"));

                columnMetas.add(meta);
            }
        }

        return columnMetas;
    }

    /**
     * 获取主键列
     */
    private Set<String> getPrimaryKeyColumns(DatabaseMetaData metaData,
                                             String catalog, String schema,
                                             String tableName) throws SQLException {
        Set<String> primaryKeys = new HashSet<>();

        try (ResultSet pkResultSet = metaData.getPrimaryKeys(catalog, schema, tableName)) {
            while (pkResultSet.next()) {
                primaryKeys.add(pkResultSet.getString("COLUMN_NAME"));
            }
        }

        return primaryKeys;
    }

    /**
     * 转换为 GenTableColumn 对象
     */
    private List<GenTableColumn> convertToGenTableColumns(List<ColumnMeta> columnMetas,
                                                          Set<String> primaryKeys) {
        List<GenTableColumn> result = new ArrayList<>();

        for (ColumnMeta meta : columnMetas) {
            GenTableColumn column = new GenTableColumn();
            String columnName = meta.columnName;

            // 基础信息
            column.setColumnName(columnName);
            column.setColumnComment(StringUtils.isNotEmpty(meta.remarks) ?
                    meta.remarks : columnName);
            column.setColumnType(buildColumnType(meta));
            column.setSort(meta.ordinalPosition);

            // Java类型映射
            column.setJavaType(jdbcTypeToJavaType(meta.dataType, meta.typeName));
            column.setJavaField(columnNameToJavaField(columnName));

            // 约束信息
            boolean isPk = primaryKeys.contains(columnName);
            column.setIsPk(isPk ? "1" : "0");

            boolean isRequired = "NO".equals(meta.isNullable) && !isPk;
            column.setIsRequired(isRequired ? "1" : "0");

            column.setIsIncrement(meta.isAutoIncrement ? "1" : "0");

            // 默认字段设置
            column.setIsInsert("1");
            column.setIsEdit(isPk ? "0" : "1"); // 主键不可编辑
            column.setIsList("1");
            column.setIsQuery("0");
            column.setQueryType("EQ");
            column.setHtmlType(getHtmlType(meta.dataType, meta.typeName));

            result.add(column);
        }

        // 按位置排序
        result.sort(Comparator.comparing(GenTableColumn::getSort));

        return result;
    }

    /**
     * 构建完整的列类型字符串
     */
    private String buildColumnType(ColumnMeta meta) {
        String typeName = meta.typeName.toUpperCase();

        if (meta.columnSize > 0) {
            if (meta.decimalDigits > 0) {
                return String.format("%s(%d,%d)", typeName, meta.columnSize, meta.decimalDigits);
            } else {
                return String.format("%s(%d)", typeName, meta.columnSize);
            }
        }

        return typeName;
    }

    /**
     * JDBC类型转Java类型
     */
    private String jdbcTypeToJavaType(int jdbcType, String typeName) {
        switch (jdbcType) {
            case Types.BIT:
            case Types.BOOLEAN:
                return "Boolean";
            case Types.TINYINT:
                return "Integer";
            case Types.SMALLINT:
            case Types.INTEGER:
                return "Integer";
            case Types.BIGINT:
                return "Long";
            case Types.FLOAT:
            case Types.REAL:
                return "Float";
            case Types.DOUBLE:
                return "Double";
            case Types.DECIMAL:
            case Types.NUMERIC:
                return "BigDecimal";
            case Types.CHAR:
            case Types.VARCHAR:
            case Types.LONGVARCHAR:
            case Types.NCHAR:
            case Types.NVARCHAR:
            case Types.LONGNVARCHAR:
                return "String";
            case Types.DATE:
                return "Date";
            case Types.TIME:
            case Types.TIMESTAMP:
                return "Date";
            case Types.BLOB:
            case Types.BINARY:
            case Types.VARBINARY:
            case Types.LONGVARBINARY:
                return "byte[]";
            case Types.CLOB:
            case Types.NCLOB:
                return "String";
            default:
                // 特殊类型处理
                if (typeName.toLowerCase().contains("bool")) {
                    return "Boolean";
                } else if (typeName.toLowerCase().contains("text")) {
                    return "String";
                }
                return "String";
        }
    }

    /**
     * 列名转Java字段名（驼峰命名）
     */
    private String columnNameToJavaField(String columnName) {
        if (StringUtils.isEmpty(columnName)) {
            return "";
        }

        // 转换为驼峰命名
        StringBuilder sb = new StringBuilder();
        boolean toUpper = false;

        for (int i = 0; i < columnName.length(); i++) {
            char c = columnName.charAt(i);

            if (c == '_') {
                toUpper = true;
            } else {
                if (toUpper) {
                    sb.append(Character.toUpperCase(c));
                    toUpper = false;
                } else {
                    sb.append(Character.toLowerCase(c));
                }
            }
        }

        return sb.toString();
    }

    /**
     * 根据数据类型获取HTML类型
     */
    private String getHtmlType(int dataType, String typeName) {
        switch (dataType) {
            case Types.BIT:
            case Types.BOOLEAN:
                return "radio";
            case Types.TINYINT:
            case Types.SMALLINT:
            case Types.INTEGER:
            case Types.BIGINT:
                return "input";
            case Types.FLOAT:
            case Types.DOUBLE:
            case Types.DECIMAL:
            case Types.NUMERIC:
                return "input";
            case Types.DATE:
                return "datetime";
            case Types.TIME:
            case Types.TIMESTAMP:
                return "datetime";
            case Types.CLOB:
            case Types.LONGVARCHAR:
            case Types.LONGNVARCHAR:
                return "textarea";
            default:
                if (typeName.toLowerCase().contains("text")) {
                    return "textarea";
                } else if (typeName.toLowerCase().contains("blob")) {
                    return "upload";
                }
                return "input";
        }
    }


    /**
     * 内部列元数据类（使用简单结构，避免创建新文件）
     */
    private static class ColumnMeta {
        String columnName;
        int dataType;
        String typeName;
        int columnSize;
        int decimalDigits;
        String isNullable;
        String remarks;
        int ordinalPosition;
        boolean isAutoIncrement;
    }
}
